home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
TCP_IP
/
TNOS230S
/
RARP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-01-19
|
6KB
|
217 lines
/* Reverse Address Resolution Protocol (ARP) functions. Sits between IP and
* Level 2, mapping Level 2 addresses to IP.
*/
#include "global.h"
#include "mbuf.h"
#include "proc.h"
#include "iface.h"
#include "arp.h"
#include "cmdparse.h"
#include "pktdrvr.h"
#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: rarp.c,v 1.20 1997/01/19 21:13:05 root Exp root $";
#endif
static struct arp_stat Rarp_stat = {0, 0, 0, 0, 0, 0, 0};
static int Rwaiting = 0; /* Semaphore used when waiting for a reply */
static int dorarpquery (int argc, char *argv[], void *p);
static void rarpstat (void);
static void rarp_output (struct iface * iface, int16 hardware, char *hwaddr, char *target);
int dorarp (int argc, char **argv, void *p);
static struct cmds Rarpcmds[] =
{
{ "query", dorarpquery, 0, 3,
#ifdef fixed
"rarp query <interface> <ether addr|callsign> [<ether addr|callsign>]",
#else
"rarp query <interface> <callsign> [<callsign>]"},
#endif
{ NULLCHAR, NULL, 0, 0, NULLCHAR}
};
int
dorarp (int argc, char **argv, void *p)
{
if (argc < 2) {
rarpstat ();
return 0;
}
return subcmd (Rarpcmds, argc, argv, p);
}
static int
dorarpquery (int argc, char *argv[], void *p OPTIONAL)
{
struct iface *ifp;
char hwaddr[MAXHWALEN], qhwaddr[MAXHWALEN];
int16 hardware, t;
static const char *errmsg = "Illegal hardware address\n";
if ((ifp = if_lookup (argv[1])) == NULLIF) {
tprintf (Badinterface, argv[1]);
return -1;
}
switch (ifp->iftype->type) {
case CL_AX25:
hardware = ARP_AX25;
break;
#ifdef fixed
case CL_ETHERNET:
hardware = ARP_ETHER;
break;
default:
tputs ("Only Ethernet and AX25 interfaces allowed\n");
#else
default:
tputs ("Only AX25 interfaces allowed\n");
#endif
return -1;
}
if ((*ifp->iftype->scan) (hwaddr, argv[2]) == -1) {
tputs (errmsg);
return -1;
}
if (argc > 3 && (*ifp->iftype->scan) (qhwaddr, argv[3]) == -1) {
tputs (errmsg);
return -1;
}
if (argc == 3)
memcpy (qhwaddr, hwaddr, (size_t) ifp->iftype->hwalen);
rarp_output (ifp, hardware, hwaddr, qhwaddr);
t = Arp_type[hardware].pendtime;
++Rwaiting;
tprintf ("Trying... %2d", t);
while (t--) {
kalarm (1000L);
if (kwait (&Rwaiting) != EALARM) {
kalarm (0);
--Rwaiting;
return 0;
}
tprintf ("\b\b%2d", t);
}
tputs ("\b\bTimeout.\n");
--Rwaiting;
return 0;
}
/* Handle incoming RARP packets according to RFC 903.
*/
void
rarp_input (iface, bp)
struct iface *iface;
struct mbuf *bp;
{
struct arp rarp;
struct arp_type *at;
char shwaddr[MAXHWALEN];
Rarp_stat.recv++;
if (ntoharp (&rarp, &bp) == -1) /* Convert into host format */
return;
if (rarp.hardware >= NHWTYPES) {
/* Unknown hardware type, ignore */
Rarp_stat.badtype++;
return;
}
at = &Arp_type[rarp.hardware];
if (rarp.protocol != at->iptype) {
/* Unsupported protocol type, ignore */
Rarp_stat.badtype++;
return;
}
if ((int16) uchar (rarp.hwalen) > MAXHWALEN || uchar (rarp.pralen) != sizeof (int32)) {
/* Incorrect protocol addr length (different hw addr lengths
* are OK since AX.25 addresses can be of variable length)
*/
Rarp_stat.badlen++;
return;
}
if (memcmp (rarp.shwaddr, at->bdcst, (size_t) at->hwalen) == 0) {
/* This guy is trying to say he's got the broadcast address! */
Rarp_stat.badaddr++;
return;
}
if (rarp.opcode == REVARP_REQUEST) {
/* We are not a server, so we can only answer requests for a
* hardware address that is our own. But would be possible to
* use the ARP table to answer requests for someone elses
* IP address.
*/
if (memcmp (rarp.thwaddr, iface->hwaddr, (size_t) at->hwalen) == 0) {
memcpy (shwaddr, rarp.shwaddr, (size_t) at->hwalen);
/* Mark the end of the sender's AX.25 address
* in case he didn't
*/
if (rarp.hardware == ARP_AX25)
rarp.thwaddr[uchar (rarp.hwalen) - 1] |= E;
memcpy (rarp.shwaddr, iface->hwaddr, (size_t) at->hwalen);
rarp.sprotaddr = iface->addr;
rarp.tprotaddr = iface->addr;
rarp.opcode = REVARP_REPLY;
if ((bp = htonarp (&rarp)) == NULLBUF)
return;
if (iface->forw != NULLIF)
(void) (*iface->forw->output) (iface->forw, shwaddr, iface->forw->hwaddr, at->rarptype, bp);
else
(void) (*iface->output) (iface, shwaddr, iface->hwaddr, at->rarptype, bp);
Rarp_stat.inreq++;
}
} else {
Rarp_stat.replies++;
if (Rwaiting) {
ksignal (&Rwaiting, 1);
tprintf ("\nRARP Reply: %s %s\n",
(*at->format) (shwaddr, rarp.thwaddr),
inet_ntoa (rarp.tprotaddr));
}
}
}
/* Send a RARP request to target to resolve hardware address hwaddr */
static void
rarp_output (struct iface *iface, int16 hardware, char *hwaddr, char *target)
{
struct arp rarp;
struct mbuf *bp;
struct arp_type *at;
at = &Arp_type[hardware];
if (iface->output == NULLFP ((struct iface *, const char *, char *, int16, struct mbuf *))) /*lint !e58 */
return;
rarp.hardware = hardware;
rarp.protocol = at->iptype;
rarp.hwalen = (char) at->hwalen;
rarp.pralen = sizeof (int32);
rarp.opcode = REVARP_REQUEST;
memcpy (rarp.shwaddr, iface->hwaddr, (size_t) at->hwalen);
rarp.sprotaddr = 0;
memcpy (rarp.thwaddr, hwaddr, (size_t) at->hwalen);
rarp.tprotaddr = 0;
if ((bp = htonarp (&rarp)) == NULLBUF)
return;
(void) (*iface->output) (iface, target, iface->hwaddr, at->rarptype, bp);
Rarp_stat.outreq++;
}
static void
rarpstat ()
{
tprintf ("received %u badtype %u bogus addr %u reqst in %u replies %u reqst out %u\n",
Rarp_stat.recv, Rarp_stat.badtype, Rarp_stat.badaddr, Rarp_stat.inreq,
Rarp_stat.replies, Rarp_stat.outreq);
}